import { composeColors, color } from '../../core/color.js';

class Spinner {
  current;
  intervalId;
  logs;
  message;
  text;
  decoration;
  symbols;
  interval;
  constructor(text = "", decoration = composeColors(color.bold, color.yellow)) {
    this.current = 0;
    this.decoration = decoration;
    this.intervalId = null;
    this.logs = [];
    this.symbols = ["\u2596", "\u2598", "\u259D", "\u2597"];
    this.interval = 120;
    this.text = text;
    if (!text.includes("{{spinner}}")) {
      this.text = "{{spinner}} " + text;
    }
  }
  clear(moveUp = false) {
    if (!this.message) {
      return;
    }
    const lines = this.message.split("\n");
    if (this.logs.length > 0) {
      lines.push(...this.logs);
    }
    lines.forEach((line, index) => {
      process.stdout.write("\r" + " ".repeat(line?.length));
      if (moveUp || index < lines.length - 1) {
        process.stdout.write("\x1B[1A");
      }
    });
    if (this.logs.length > 1) {
      process.stdout.write("\x1B[1A");
    }
  }
  render() {
    const spinner = this.renderSpinner();
    this.clear();
    this.message = this.text.replaceAll("{{spinner}}", spinner);
    process.stdout.write("\r" + this.message);
    if (this.logs.length > 0) {
      process.stdout.write("\n" + this.logs.join("\n"));
    }
    this.current = (this.current + 1) % this.symbols.length;
  }
  renderSpinner() {
    return this.decoration(this.symbols[this.current]);
  }
  getLogs() {
    return this.logs;
  }
  setLogs(...logs) {
    this.logs = logs;
  }
  setText(text, defaultSpinner = true) {
    this.text = text;
    if (defaultSpinner && !text.includes("{{spinner}}")) {
      this.text = "{{spinner}} " + text;
    }
  }
  start() {
    this.intervalId = setInterval(() => this.render(), this.interval);
  }
  stop(moveUp = true, clear = true) {
    if (this.intervalId) {
      clearInterval(this.intervalId);
      this.intervalId = null;
      this.render();
      if (clear) {
        this.clear(moveUp);
      }
      this.message = null;
    }
  }
}

export { Spinner };
